<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
	xmlns="http://www.w3.org/1999/xhtml"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:ev="http://www.w3.org/2001/xml-events"
	xmlns:ccts="urn:un:unece:uncefact:documentation:standard:CoreComponentsTechnicalSpecification:2"
	xmlns:xf="http://www.w3.org/2002/xforms"
	xmlns:ebfuncs="http://code.google.com/p/eb-forms/functions"
	exclude-result-prefixes="#all"> 
	
	<xsl:import href="GlobalTemplates.xsl"/>
	<xsl:import href="GlobalFunctions.xsl"/>
	<xsl:import href="Typelist.xsl"/>
	
	<!-- 
		This template starts generation of the gui part from the XForms document. It creates a
		div for the root element of the message and then calls the template GuiElements to walk
		through the rest of the message.
	-->
	<xsl:template name="GenerateGui">
		<xsl:param name="type" as="xsd:string" required="yes" />
		<xsl:param name="prefix" as="xsd:string" required="yes" />
		
		<xsl:variable name="den" 
			select="ebfuncs:getStrippedDen( 
				$global.doc.schema.root/xsd:schema/xsd:complexType[@name = substring-after( $type, ':' )] )"
		/>
		
		<xsl:variable name="ref">
			<xsl:text>instance( '</xsl:text>
			<xsl:value-of select="$global.instance.message" />
			<xsl:text>' )</xsl:text>
		</xsl:variable>
		
		<div class="{$den}">
			<h1><xsl:value-of select="xsd:annotation/xsd:documentation/ccts:Name" /></h1>
			
			<xsl:call-template name="GuiElements">
				<xsl:with-param name="element.type" select="$type" />
				<xsl:with-param name="element.ref" select="$ref" />
				<xsl:with-param name="element.prefix" select="$prefix"/>
				<xsl:with-param name="element.schema" select="document-uri( / )" />
			</xsl:call-template>
		</div>
	</xsl:template>
	
	<!--
		Generates the gui elements for each element found in the message.
	-->
	<xsl:template name="GuiElements">
		<xsl:param name="element.type" as="xsd:string" required="yes"/>
		<xsl:param name="element.ref" as="xsd:string" required="yes" />
		<xsl:param name="element.prefix" as="xsd:string" required="yes" />
		<xsl:param name="element.schema" as="xsd:string" required="yes" />
		
		<xsl:variable name="element.type.children">
			<xsl:call-template name="GetChildElements">
				<xsl:with-param name="parent" select="substring-after( $element.type, ':' )" />
				<xsl:with-param name="parent.schema" select="$element.schema" />
			</xsl:call-template>			
		</xsl:variable>
		
		<xsl:for-each select="$element.type.children/xsd:element">
			<xsl:sort select="position" />
			
			<xsl:variable name="element.ref" select="if( $element.ref = '' ) 
				then concat( $element.prefix, ':', @name )
				else concat( $element.ref, '/', $element.prefix, ':', @name )" />
			
			<xsl:choose>
				<xsl:when test="@maxOccurs = 'unbounded' or @maxOccurs > 1">
					<xsl:variable name="repeat.id">repeat.<xsl:value-of select="generate-id()" /></xsl:variable>
					
					<xf:repeat nodeset="{$element.ref}" id="{$repeat.id}">
						<xsl:call-template name="HandleChildren" >
							<xsl:with-param name="element.schema" select="$element.schema" />
							<xsl:with-param name="element.ref"></xsl:with-param>
							<xsl:with-param name="element.prefix" select="$element.prefix" />
						</xsl:call-template>
						
						<xsl:if test="ebfuncs:transformMode() != 'read'">
							<xf:trigger>
								<xf:label>
									<xsl:value-of select="concat( 'Delete ', ebfuncs:getBusinessTerm( . ) )" />
								</xf:label>
								<xf:delete nodeset="{$element.ref}" at="index('{$repeat.id}')"
									ev:event="DOMActivate">
								</xf:delete>
							</xf:trigger>
						</xsl:if>
					</xf:repeat>
					<xsl:if test="ebfuncs:transformMode() != 'read'">
						<xf:trigger>
							<xf:label>
								<xsl:value-of	select="concat( 'Nieuwe ', ebfuncs:getBusinessTerm( . ) )" />
							</xf:label>
							<xf:action ev:event="DOMActivate">
								<xf:insert nodeset="{$element.ref}" position="before"
									at="count( {$element.ref} )">
								</xf:insert>
							</xf:action>
						</xf:trigger>
					</xsl:if>
				</xsl:when>
				<xsl:otherwise>
					<xsl:call-template name="HandleChildren" >
						<xsl:with-param name="element.schema" select="$element.schema" />
						<xsl:with-param name="element.ref" select="$element.ref" />
						<xsl:with-param name="element.prefix" select="$element.prefix" />
					</xsl:call-template>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:for-each>
	</xsl:template>
	
	<!-- 
		Context = The children of an ABIE or an ASBIE.
	-->
	<xsl:template name="HandleChildren">
		<xsl:param name="element.schema" as="xsd:string" required="yes" />
		<xsl:param name="element.prefix" as="xsd:string" required="yes" />
		<xsl:param name="element.ref" as="xsd:string" required="yes" />
		
		<xsl:choose>
			<!-- 
				When the current element is a BBIE, a qualified or an unqualified datatype, it has 
				no children. So the next thing to do is to generate the right xforms elements for 
				this BBIE. 
			-->
			<xsl:when test="ebfuncs:getAcronym( . ) = 'BBIE'">
				<xsl:call-template name="HandleDataType">
					<xsl:with-param name="element.parent.schema" select="$element.schema" />
					<xsl:with-param name="element.ref" select="$element.ref" />
				</xsl:call-template>
			</xsl:when>
			<xsl:otherwise>
				<xsl:variable name="element.child.namespace" 
					select="namespace-uri-for-prefix( substring-before( @type, ':' ), . )"/>
				
				<xsl:variable name="element.schema.namespace" select="if( $element.schema = '' ) 
					then $global.doc.schema.root/xsd:schema/@targetNamespace
					else document( $element.schema )/xsd:schema/@targetNamespace"/>
				
				<div class="{ebfuncs:getStrippedDen( . )}">
					<xsl:if test="ebfuncs:displayLable( ebfuncs:getDen( . ) ) = true()">
						<h2><xsl:value-of select="ebfuncs:getBusinessTerm( . )"/></h2>
					</xsl:if>
					<xsl:choose>
						<!-- 
							When the child is in another namespace this means that it's declared in
							another schema document.
						-->
						<xsl:when test="$element.schema.namespace != $element.child.namespace">
							<xsl:variable name="element.child.schema">
								<xsl:call-template name="GetDataTypeDocument">
									<xsl:with-param name="element.type" select="@type" />
									<xsl:with-param name="element.schema" select="$element.schema" />
								</xsl:call-template>
							</xsl:variable>
							
							<xsl:variable name="prefix.next" select="substring-before( @type, ':' )"/>
							
							<xsl:call-template name="GuiElements">
								<xsl:with-param name="element.type" select="@type"/>
								<xsl:with-param name="element.ref" select="$element.ref" />
								<xsl:with-param name="element.prefix" select="$prefix.next" />
								<xsl:with-param name="element.schema" select="$element.child.schema" />
							</xsl:call-template>
						</xsl:when>
						<!-- 
							Otherwhise the element is declared in the same schema as it's parent.
						-->
						<xsl:otherwise>
							<xsl:call-template name="GuiElements">
								<xsl:with-param name="element.type" select="@type"/>
								<xsl:with-param name="element.ref" select="$element.ref" />
								<xsl:with-param name="element.prefix" select="$element.prefix" />
								<xsl:with-param name="element.schema" select="$element.schema" />
							</xsl:call-template>
						</xsl:otherwise>
					</xsl:choose>
				</div>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<!-- 
		Context is a xsd:element with acronym = BBIE.
	-->
	<xsl:template name="HandleDataType">
		<xsl:param name="element.parent.schema" required="yes" />
		<xsl:param name="element.ref" required="yes" />
		
		<xsl:variable name="element.type.schema">
			<xsl:call-template name="GetDataTypeDocument">
				<xsl:with-param name="element.type" select="@type" />
				<xsl:with-param name="element.schema" select="$element.parent.schema" />
			</xsl:call-template>
		</xsl:variable>
		
		<xsl:variable name="element.type.simple">
			<xsl:call-template name="BasedOnSimpleType">
				<xsl:with-param name="element.type" select="@type" />
				<xsl:with-param name="element.type.schema" select="$element.type.schema" />
			</xsl:call-template>
		</xsl:variable>
		
		<xsl:choose>
			<!--
				The data type is an Code Type or an ID Type which is based on a content type. 
			-->
			<xsl:when test="$element.type.simple = true()">
				<xsl:variable name="element.type.base">
					<xsl:call-template name="GetBaseType">
						<xsl:with-param name="element.type" select="@type" />
						<xsl:with-param name="element.type.schema" 
							select="$element.type.schema" />
					</xsl:call-template>
				</xsl:variable>
				
				<xsl:variable name="nodeset">
					<xsl:text>instance( '</xsl:text>
					<xsl:value-of select="concat( 'instance.codes.'
						, concat( concat( @type, '.' ), $element.type.base ) )" />
					<xsl:text>' )/xsd:simpleType/xsd:restriction/xsd:enumeration</xsl:text>
				</xsl:variable>
				
				<div class="{ebfuncs:getStrippedDen( . )}">
					<xf:select1 ref="{$element.ref}">
						<xsl:if test="ebfuncs:displayLable( ebfuncs:getDen( . ) )">
							<xf:label><xsl:value-of 
								select="concat( ebfuncs:getBusinessTerm( . ), ': ' )" />
							</xf:label>
						</xsl:if>
						<xf:itemset nodeset="{$nodeset}">
							<xf:label ref="xsd:annotation/xsd:documentation/ccts:Name" />
							<xf:value ref="@value" />
						</xf:itemset>
					</xf:select1>
				</div>
			</xsl:when>
			<xsl:otherwise>
				<xsl:variable name="element.attributes">
					<xsl:call-template name="GetUsedAttributes">
						<xsl:with-param name="element.den"  select="ebfuncs:getDen( . )"/>
						<xsl:with-param name="element.type" select="@type" />
						<xsl:with-param name="element.type.schema" select="$element.type.schema" />
					</xsl:call-template>
				</xsl:variable>
			
				<xsl:element name="div">
					<xsl:attribute name="class" 
						select="replace( replace( ebfuncs:getDen( . ), ' ', '' ), '\.', '__' )" />
					
					<!--
						If the element has more then 0 used attributes a simple and a detailed 
						mode for the element is generated. In the detailed mode the forms shows
						the attributes to the user. In simple mode those are hidden.
						
						Otherwhise only a field for the content of the BBIE has to be created.
					-->
					<xsl:choose>
						<xsl:when test="count( $element.attributes/attribute ) > 0">
							<xsl:call-template name="GenerateSwitchCode" >
								<xsl:with-param name="element.ref" select="$element.ref" />
								<xsl:with-param name="element.attributes" select="$element.attributes" />
							</xsl:call-template>
						</xsl:when>
						<xsl:otherwise>
							<!-- There are no attributes used for by this element -->
							<xsl:element name="xf:input">
								<xsl:attribute name="ref">
									<xsl:value-of select="$element.ref"/>
								</xsl:attribute>
								<xsl:element name="xf:label">
									<xsl:value-of select="concat( ebfuncs:getBusinessTerm( . ), ': ' )" />
								</xsl:element>
							</xsl:element>
						</xsl:otherwise>
					</xsl:choose>
				</xsl:element>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template name="GenerateSwitchCode">
		<xsl:param name="element.ref" as="xsd:string" required="yes" />
		<xsl:param name="element.attributes" as="item()*" required="yes" />
		
		<xsl:variable name="case.id" select="generate-id()"></xsl:variable>
		
		<xf:switch>
			<xf:case id="{concat( $case.id, '_simple' )}">
				<div class="bbie">
					<div class="element">
						<xf:input ref="{$element.ref}">
							<xf:label><xsl:value-of 
								select="concat( ebfuncs:getBusinessTerm( . ), ': ' )" /></xf:label>
						</xf:input>
					</div>
					<div class="element">
						<xf:trigger>
							<xf:label>Show details</xf:label>
							<xf:action ev:event="DOMActivate">
								<xf:toggle case="{concat( $case.id, '_detailed' )}" />
							</xf:action>
						</xf:trigger>
					</div>
				</div>
			</xf:case>
			<xf:case id="{concat( $case.id, '_detailed' )}">
				<div class="bbie">
					<div class="element">
						<xf:input ref="{$element.ref}">
							<xf:label><xsl:value-of 
								select="concat( ebfuncs:getBusinessTerm( . ), ': ' )" /></xf:label>
						</xf:input>
					</div>
					<div class="element">
						<xf:trigger>
							<xf:label>Hide details</xf:label>
							<xf:action ev:event="DOMActivate">
								<xf:toggle case="{concat( $case.id, '_simple' )}" />
							</xf:action>
						</xf:trigger>
					</div>
				</div>
				<div class="Supplementary">
					<xsl:for-each select="$element.attributes/attribute">
						<xsl:call-template name="GenerateAttributeCode">
							<xsl:with-param name="element.ref" select="$element.ref" />
							<xsl:with-param name="element.attribute" select="." />
						</xsl:call-template>
					</xsl:for-each>
				</div>
			</xf:case>
		</xf:switch>
	</xsl:template>
	
	<xsl:template name="GenerateAttributeCode">
		<xsl:param name="element.ref" as="xsd:string" required="yes" />
		<xsl:param name="element.attribute" as="item()" required="yes" />
		
		<!-- The attribute is either a list or a simple type -->
		<xsl:choose>
			<xsl:when test="count( $global.element.types.used/codelistTypes/attribute
				[@name = $element.attribute/@name and @type = $element.attribute/@type] ) = 1">
				<xf:select1 ref="{concat( concat( $element.ref, '/@' ), $element.attribute/@name )}">
					<xf:label><xsl:value-of select="$element.attribute/@name"/>: </xf:label>
					<xf:itemset>
						<xsl:attribute name="nodeset">
							<xsl:text>instance( '</xsl:text>
							<xsl:value-of 
								select="concat( 'instance.codes.', $element.attribute/@name ) "/>
							<xsl:value-of select="concat( '.', $element.attribute/@type )" />
							<xsl:text>' )/xsd:simpleType/xsd:restriction/xsd:enumeration</xsl:text>
						</xsl:attribute>
						<xf:label ref="xsd:annotation/xsd:documentation/ccts:Name" />
						<xf:value ref="@value" />
					</xf:itemset>
				</xf:select1>
			</xsl:when>
			<xsl:otherwise>
				<xf:input>
					<xsl:attribute name="ref">
						<xsl:value-of select="$element.ref"/>
						<xsl:text>/@</xsl:text>
						<xsl:value-of select="$element.attribute/@name" />
					</xsl:attribute>
					<xf:label><xsl:value-of 
						select="concat( $element.attribute/@name, ': ' )" /></xf:label>
				</xf:input>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
</xsl:stylesheet>